﻿#include "VAOneXMLAdaptorSeaBeam.h"
#include "rapidxml.hpp"
#include <QFile>
#include <iostream>
#include <QDebug>
#include "FITKAcousticsModel/FITKAbstractSEASubSys.h"
#include "FITKAcousticsModel/FITKSEASubSysBeam.h"
#include "FITKAcousticsPhysics/FITKAcousticsPhysics.h"
#include "FITKAcousticsPhysics/FITKAcousticsSpectraManager.h"
#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"
#include "FITKAcousticsPhysics/FITKAcousticsAbsPhysicsProp.h"
#include "FITKAcousticsModel/FITKAcousticsDiscModel.h"
#include "FITKAcousticsModel/FITKAcousticsSEAModel.h"
#include "FITKAcousticsModel/FITKAbstractSEAFace.h"

namespace IO
{
    bool VAOneXMLAdaptorSeaBeam::adaptR()
    {
        bool b = true;

        //指针检查
        if(nullptr == _node) return false;

        Acoustics::FITKAcousticsSEASubSysManager *dataManager = dynamic_cast<Acoustics::FITKAcousticsSEASubSysManager*>(_dataObj);
        if (nullptr == dataManager) return false;

        rapidxml::xml_node<char>* node = _node->first_node("Beam");
        while (nullptr != node)
        {
            Acoustics::FITKSEASubSysBeam *data =  new Acoustics::FITKSEASubSysBeam;
            readCell(node, data);

            dataManager->appendDataObj(data);

            node = node->next_sibling("Beam");
        }

        // 返回操作是否成功
        return b;
    }

    bool VAOneXMLAdaptorSeaBeam::adaptW()
    {
        Acoustics::FITKAcousticsSEASubSysManager *dataManager = dynamic_cast<Acoustics::FITKAcousticsSEASubSysManager*>(_dataObj);

        if ((nullptr == dataManager) || (nullptr == _node)) return false;

        bool b = true;

        // 获取列表
        QList<Acoustics::FITKAbstractSEASubSys*> list = dataManager->getSubSysByType(Acoustics::FITKAbstractSEASubSys::SEABeam);

        // 循环处理shell
        for (auto data : list)
        {
            // 创建节点
            rapidxml::xml_node<char>* node = createNodeElement(_node, "Beam");
            if (nullptr == node) continue;

            //单个节点信息写入
            writeCell((Acoustics::FITKSEASubSysBeam *)data, node);
        }

        // 返回操作是否成功
        return b;
    }

    void VAOneXMLAdaptorSeaBeam::readPhyProperty(rapidxml::xml_node<char> *node, Acoustics::FITKSEASubSysBeam *data)
    {
        bool bOK = true;

        QString str = readStrAttribute(node, "crosssection", &bOK);
        if (true != bOK)
        {
            qDebug() << "beam read crosssection failed";
            return;
        }

        int id = getPhyPropertyId(str);
        data->setPropSection(id);
    }

    void VAOneXMLAdaptorSeaBeam::readDamping(rapidxml::xml_node<char>* node, Acoustics::FITKSEASubSysBeam *data)
    {
        //damping_flexure_x="1% loss factor"
        //damping_flexure_y="1% loss factor"
        //damping_extension="1% loss factor"
        //damping_torsion="1% loss factor"

        bool bOK = true;
        QString damping_flexure_x = readStrAttribute(node, "damping_flexure_x", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read damping_flexure_x failed";
            return;
        }

        QString damping_flexure_y = readStrAttribute(node, "damping_flexure_y", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read damping_flexure_y failed";
            return;
        }

        QString damping_extension = readStrAttribute(node, "damping_extension", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read damping_extension failed";
            return;
        }

        QString damping_torsion = readStrAttribute(node, "damping_torsion", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read damping_torsion failed";
            return;
        }

        //获取physis管理器
        Acoustics::FITKAcousticsPhysics* phyMgr = FITKAPP->getGlobalData()->getPhysicsData<Acoustics::FITKAcousticsPhysics>();
        if (nullptr == phyMgr) return;

        //获取频谱管理器
        Acoustics::FITKAcousticsSpectraManager* spectraMgr = phyMgr->getFITKAcousticsSpectraManager();
        if (nullptr == spectraMgr) return;

        //将字符串信息转换成ojectid
        QList<Acoustics::FITKAcousticsAbstractSpectra*> spectraList = spectraMgr->getSpectraByType(Acoustics::FITKAcousticsAbstractSpectra::AcousticsSpectraType::Damping);
        for (auto key : spectraList)
        {
            QString name = key->getDataObjectName();
            if (damping_flexure_x == name)
            {
                data->setFlexureXSpectraID(key->getDataObjectID());
            }
            if (damping_flexure_y == name)
            {
                data->setFlexureYSpectraID(key->getDataObjectID());
            }
            if (damping_extension == name)
            {
                data->setExtensionZSpectraID(key->getDataObjectID());
            }
            if (damping_torsion == name)
            {
                data->setTorsionZZSpectraID(key->getDataObjectID());
            }
        }
    }

    void VAOneXMLAdaptorSeaBeam::readWave(rapidxml::xml_node<char> *node, Acoustics::FITKSEASubSysBeam *data)
    {
        //include_in_matrix_solution_flexure_x="true"
        //include_in_matrix_solution_flexure_y="true"
        //include_in_matrix_solution_extension="true"
        //include_in_matrix_solution_torsion="true"

        if ((nullptr == node) || (nullptr == data)) return;

        bool bOK = true;

        QString str = readStrAttribute(node, "include_in_matrix_solution_flexure_x", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read include_in_matrix_solution_flexure_x error";
            return;
        }
        data->setFlexureXInSEAMatrixSolution(strToBool(str));

        str = readStrAttribute(node, "include_in_matrix_solution_flexure_y", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read include_in_matrix_solution_flexure_y error";
            return;
        }
        data->setFlexureYInSEAMatrixSolution(strToBool(str));

        str = readStrAttribute(node, "include_in_matrix_solution_extension", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read include_in_matrix_solution_extension error";
            return;
        }
        data->setExtensionZInSEAMatrixSolution(strToBool(str));

        str = readStrAttribute(node, "include_in_matrix_solution_torsion", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read include_in_matrix_solution_flexure_y error";
            return;
        }
        data->setTorsionZZInSEAMatrixSolution(strToBool(str));
    }

    void VAOneXMLAdaptorSeaBeam::readModelDensity(rapidxml::xml_node<char>* node, Acoustics::FITKSEASubSysBeam *data)
    {
        if ((nullptr == node) || (nullptr == data)) return;

        bool bOK = true;

        //不做判断 字段可能不存在
        QString str = readStrAttribute(node, "ud_modal_density_flexure_x", &bOK);
        data->setFlexureXModelDensityState(false);
        int id = getModalDensityId(str);
        if (-1 != id)
        {
            data->setFlexureXModelDensityState(true);
            data->setFlexureXModelDensityID(id);
        }

        //不做判断 字段可能不存在
        str = readStrAttribute(node, "ud_modal_density_flexure_y", &bOK);
        data->setFlexureYModelDensityState(false);
        id = getModalDensityId(str);
        if (-1 != id)
        {
            data->setFlexureYModelDensityState(true);
            data->setFlexureYModelDensityID(id);
        }

        //不做判断 字段可能不存在
        str = readStrAttribute(node, "ud_modal_density_extension", &bOK);
        data->setExtensionZModelDensityState(false);
        id = getModalDensityId(str);
        if (-1 != id)
        {
            data->setExtensionZModelDensityState(true);
            data->setExtensionZModelDensityID(id);
        }

        //不做判断 字段可能不存在
        str = readStrAttribute(node, "ud_modal_density_torsion", &bOK);
        data->setTorsionZZModelDensityState(false);
        id = getModalDensityId(str);
        if (-1 != id)
        {
            data->setTorsionZZModelDensityState(true);
            data->setTorsionZZModelDensityID(id);
        }
    }

    void VAOneXMLAdaptorSeaBeam::readCell(rapidxml::xml_node<char> *node, Acoustics::FITKSEASubSysBeam *data)
    {
        if ((nullptr == node) || (nullptr == data)) return;

        bool bOK = true;

        //<Name>beam</Name>
        rapidxml::xml_node<char> * child = node->first_node("Name");
        if (nullptr != child)
        {
            QString name = readStrNodeValue(child, &bOK);
            if (true != bOK)
            {
                qDebug()<<"read cavity name error";
                return;
            }

            data->setDataObjectName(name);//名称可以为空，但是节点不能为空
        }

        //crosssection="Uniform shell"
        readPhyProperty(node, data);

        readDamping(node, data);

        //波数据
        readWave(node, data);

        //模态密度数据
        readModelDensity(node, data);

        QList<Acoustics::FITKAbstractSEASubSysWithNodes::SubSysNode> list;

        //读取nodeid信息
        child = node->first_node("NodeRef");
        while (nullptr != child)
        {
            int nodeId = readIntAttribute(child, "nodeid", &bOK);
            if (true != bOK)
            {
                qDebug()<<"beam node id read error";
                return;
            }

            Acoustics::FITKAbstractSEASubSysWithNodes::SubSysNode pNode;
            pNode._id = nodeId;
            pNode._type = Acoustics::FITKAbstractSEASubSysWithNodes::Path;
            list<<pNode;

            child = child->next_sibling("NodeRef");
        }

        int oriNodeId = readIntAttribute(node, "orienting_node_id", &bOK);
        if (true != bOK)
        {
            qDebug()<<"beam orienting_node_id read error";
            return;
        }
        Acoustics::FITKAbstractSEASubSysWithNodes::SubSysNode pNode;
        pNode._id = oriNodeId;
        pNode._type = Acoustics::FITKAbstractSEASubSysWithNodes::Path;
        list<<pNode;

        if (2 <= list.size())
        {
            list.first()._type = Acoustics::FITKAbstractSEASubSysWithNodes::Start;
            list.last()._type = Acoustics::FITKAbstractSEASubSysWithNodes::Finish;
        }
        data->setNodes(list);
    }

    void VAOneXMLAdaptorSeaBeam::writePhyProperty(Acoustics::FITKSEASubSysBeam *data, rapidxml::xml_node<char> *node)
    {
        if ((nullptr == node) || (nullptr == data)) return;

        QString name = getPhyPropertyName(data->getPropSectionID());

        writeAttribute(node, "crosssection", name);
    }

    void VAOneXMLAdaptorSeaBeam::writeDamping(Acoustics::FITKSEASubSysBeam *data, rapidxml::xml_node<char> *node)
    {
        if ((nullptr == node) || (nullptr == data)) return;

        //获取physis管理器
        Acoustics::FITKAcousticsPhysics* phyMgr = FITKAPP->getGlobalData()->getPhysicsData<Acoustics::FITKAcousticsPhysics>();
        if (nullptr == phyMgr) return;

        //获取频谱管理器
        Acoustics::FITKAcousticsSpectraManager* spectraMgr = phyMgr->getFITKAcousticsSpectraManager();
        if (nullptr == spectraMgr) return;

        QString flexurex = "";
        QString flexurey = "";
        QString extension = "";
        QString torsion = "";

        //damping_flexure_x="1% loss factor"
        //damping_flexure_y="1% loss factor"
        //damping_extension="1% loss factor"
        //damping_torsion="1% loss factor"

        //将ojectid信息转换成字符串
        QList<Acoustics::FITKAcousticsAbstractSpectra*> spectraList = spectraMgr->getSpectraByType(Acoustics::FITKAcousticsAbstractSpectra::AcousticsSpectraType::Damping);
        for (auto key : spectraList)
        {
            QString name = key->getDataObjectName();
            int id = key->getDataObjectID();
            if (data->getFlexureXSpectraID() == id) flexurex = name;
            if (data->getFlexureYSpectraID() == id) flexurey = name;
            if (data->getExtensionZSpectraID() == id) extension = name;
            if (data->getTorsionZZSpectraID() == id) torsion = name;
        }

        writeAttribute(node, "damping_flexure_x", flexurex);
        writeAttribute(node, "damping_flexure_y", flexurey);
        writeAttribute(node, "damping_extension", extension);
        writeAttribute(node, "damping_torsion", torsion);
    }

    void VAOneXMLAdaptorSeaBeam::writeWave(Acoustics::FITKSEASubSysBeam *data, rapidxml::xml_node<char> *node)
    {
        if ((nullptr == node) || (nullptr == data)) return;

        writeAttribute(node, "include_in_matrix_solution_flexure_x", boolToStr(data->getFlexureXInSEAMatrixSolution()));
        writeAttribute(node, "include_in_matrix_solution_flexure_y", boolToStr(data->getFlexureYInSEAMatrixSolution()));
        writeAttribute(node, "include_in_matrix_solution_extension", boolToStr(data->getExtensionZInSEAMatrixSolution()));
        writeAttribute(node, "include_in_matrix_solution_torsion", boolToStr(data->getTorsionZZInSEAMatrixSolution()));
    }

    void VAOneXMLAdaptorSeaBeam::writeModelDensity(Acoustics::FITKSEASubSysBeam *data, rapidxml::xml_node<char> *node)
    {
        if ((nullptr == node) || (nullptr == data)) return;

        bool ok = true;
        /*
        ok &= writeAttribute(node, "ud_modal_density_flexure_x", getModalDensityName(data->getFlexureXModelDensityID()));
        ok &= writeAttribute(node, "ud_modal_density_flexure_y", getModalDensityName(data->getFlexureYModelDensityID()));
        ok &= writeAttribute(node, "ud_modal_density_extension", getModalDensityName(data->getExtensionZModelDensityID()));
        ok &= writeAttribute(node, "ud_modal_density_torsion", getModalDensityName(data->getTorsionZZModelDensityID()));
        */
        ok &= writeAttribute(node, "xsea_alias_flexure_x", getModalDensityName(data->getFlexureXModelDensityID()));
        ok &= writeAttribute(node, "xsea_alias_flexure_y", getModalDensityName(data->getFlexureYModelDensityID()));
        ok &= writeAttribute(node, "xsea_alias_extension", getModalDensityName(data->getExtensionZModelDensityID()));
        ok &= writeAttribute(node, "xsea_alias_torsion", getModalDensityName(data->getTorsionZZModelDensityID()));

        ok &= writeAttribute(node, "modal_flexure_x", boolToStr(data->getFlexureXModelDensityState()));
        if (ok == false) return;
        ok &= writeAttribute(node, "modal_flexure_y", boolToStr(data->getFlexureYModelDensityState()));
        if (ok == false) return;
        ok &= writeAttribute(node, "modal_extension", boolToStr(data->getExtensionZModelDensityState()));
        if (ok == false) return;
        ok &= writeAttribute(node, "modal_torsion", boolToStr(data->getTorsionZZModelDensityState()));
        if (ok == false) return;
    }

    void VAOneXMLAdaptorSeaBeam::writeCell(Acoustics::FITKSEASubSysBeam *data, rapidxml::xml_node<char> *node)
    {
        if ((nullptr == node) || (nullptr == data)) return;

        //<Name>beam</Name>
        rapidxml::xml_node<char> * nameChild = createNodeElement(node, "Name", data->getDataObjectName());
        if (nullptr == nameChild)
        {
            qDebug()<<"beam name write failed";
            return;
        }

		// <Note/>
		rapidxml::xml_node<char> * noteChild = createNodeElement(node, "Note", "");
		if (nullptr == noteChild) return;

        //物理属性
        writePhyProperty(data, node);

        //损耗数据
        writeDamping(data, node);

        // oriented_axis
        writeAttribute(node, "oriented_axis", "X");
        // orienting_node_id
        QList<int> list = data->getNodeIDs();
        writeAttribute(node, "orienting_node_id", list.last());

        //波的数据
        writeWave(data, node);

        //模态数据
        writeModelDensity(data, node);

        //读取nodeid信息
        for (int i = 0; i < list.size() - 1; i++)
        {
            nameChild = createNodeElement(node, "NodeRef");
            if (nullptr == nameChild) continue;
            writeAttribute(nameChild, "nodeid", list[i]);
        }
    }
}
